#!/usr/bin/python

# InnerSpace
# Copyright (C) 1999-2006 Phil Christensen
#
# $Id: editors.py 157 2007-02-11 18:37:33Z phil $
#
# See LICENSE for details

"""
Editors

Stability: barely stable

Contains the routines to manipulate and interact with the 
object editors provided by the client.
"""

from inner.space import errors, security, actions

import types, copy

def edit_verb(user, obj, name, request_id=None):
	"""Present a v editing window for a v on 'obj' called 'name',
	through the connection to user."""
	security.check_allowed(user, 'edit_verb', obj)
	from inner.space import verb
	
	if not(user.is_connected_player()):
		raise errors.PermissionError, "A non-connected-player entity cannot edit a verb!"
	info = {u'origin':unicode(obj), u'request_id':request_id}
	v = None
	if(obj.has_verb(name)):
		v = obj._vdict[name]
		if not(v.is_readable()):
			raise errors.PermissionError, "The v '" + name + "' is not readable to you."
		info[u'names'] = v.names
		info[u'code'] = v.get_code()
		info[u'owner'] = unicode(v.get_owner())
	else:
		info[u'names'] = [name]
		info[u'code'] = u''
		info[u'owner'] = unicode(user)
		
	#---callbacks------------------------
	def ok(response):
		from inner.space import auth
		auth.user_activate(user);
		
		try:
			if(response):
				#response = actions.ununicodify(response)
				if(v):
					obj.remove_verb(name)
				if(v):
					def preset_verb_acl(new_verb):
						new_verb._vitals[u'acl'] = v._vitals[u'acl']
					acl_func = preset_verb_acl
				else:
					acl_func = security.default_verb_acl
				obj.add_verb(response[u'code'], response[u'names'], auth.get_registry().get(response[u'owner']), acl_configure=acl_func)
		finally:
			auth.user_deactivate()
			
	def ko(failure):
		print failure
	#-------------------------------------
	return user._connection.open_editor('verb', info, ok, ko)

def edit_property(user, obj, name, request_id=None):
	"""Present a prop editing window for a prop on 'obj' called 'name',
	through the connection to user."""
	security.check_allowed(user, 'edit_prop', obj)
	from inner.space import prop

	if not(user.is_connected_player()):
		raise errors.PermissionError, "A non-connected-player entity cannot edit a property!"
	info = {u'origin':unicode(obj), u'request_id':request_id, u'name':name}
	p = None
	
	import entity
	
	if(obj.has_property(name)):
		p = obj._vdict[name]
		if not(p.is_readable()):
			raise errors.PermissionError, "The verb '" + name + "' is not readable to you."
		info[u'eval_type'] = p.get_eval_type()
		if(info[u'eval_type'] == prop.EVAL_CODE or info[u'eval_type'] == prop.EVAL_DYNAMIC_CODE):
			info[u'value'] = p.code
		elif(info[u'eval_type'] == prop.EVAL_PICKLE):
			info[u'value'] = pickle.dumps(p.get_value())
		else:
			info[u'value'] = unicode(p.get_value())
		info[u'owner'] = unicode(p.get_owner())
	else:
		info[u'eval_type'] = prop.EVAL_STRING
		info[u'value'] = u""
		info[u'owner'] = unicode(user)
		
	#---callbacks------------------------
	def ok(response):
		from inner.space import auth
		auth.user_activate(user);
		
		try:
			if(response):
				#response = actions.ununicodify(response)
				owner = auth.get_registry().get(response[u'owner'])
				if(response[u'eval_type'] == prop.EVAL_ENTITY):
					response[u'value'] = auth.get_registry().get(response[u'value'])
				if(p):
					def preset_prop_acl(new_prop):
						new_prop._vitals[u'acl'] = p._vitals[u'acl']
					obj.remove_property(info[u'name'])
					acl_func = preset_prop_acl
				else:
					acl_func = security.default_property_acl
				obj.add_property(response[u'name'], response[u'value'], owner, response[u'eval_type'], acl_configure=acl_func)
		finally:
			auth.user_deactivate();
	
	def ko(failure):
		print failure
	#-------------------------------------
	return user._connection.open_editor('prop', info, ok, ko)

def edit_entity(user, obj, request_id=None):
	"""Present an object editing window for 'obj'
	through the connection to user."""
	security.check_allowed(user, 'edit_entity', obj)
	if not(user.is_connected_player()):
		raise errors.PermissionError, "A non-connected-player entity cannot edit an object!"
	info = obj.get_details_unicode()
	info[u'request_id'] = request_id
	#---callbacks------------------------
	def ok(response):
		from inner.space import auth
		auth.user_activate(user);
		
		try:
			if(response):
				#response = actions.ununicodify(response)
				registry = auth.get_registry()
				registry.rename(obj, response[u'name'])
				obj.set_parent(registry.get(response[u'parent']))
				obj.set_location(registry.get(response[u'location']))
				
				#TODO: this will be a permanent part of the response one day
				if(response[u'owner']):
					obj.set_owner(registry.get(response[u'owner']))
				obj._vitals[u'entity_type'] = response[u'entity_type']
		finally:
			auth.user_deactivate();
	
	def ko(failure):
		print failure
	#-------------------------------------
	return user._connection.open_editor('obj', info, ok, ko)

def edit_acl(user, obj, request_id=None):
	"""
	Present an object editing window for 'obj'
	through the connection to user.
	"""
	security.check_allowed(user, 'edit_acl', obj)
	if not(user.is_connected_player()):
		raise errors.PermissionError, "A non-connected-player entity cannot edit an ACL!"
	acl = copy.copy(obj._vitals[u'acl'])
	info = {u'permissions':acl, u'request_id':request_id}
	
	#---callbacks------------------------
	def ok(response):
		from inner.space import auth
		auth.user_activate(user);
		
		try:
			if(response):
				response = actions.ununicodify(response)
				obj._vitals[u'acl'] = []
				for item in response[u'permissions']:
					if(item[0] == u'allow'):
						security.allow(item[1], item[2], obj)
					elif(item[0] == u'deny'):
						security.deny(item[1], item[2], obj)
		finally:
			auth.user_deactivate()
	
	def ko(failure):
		print failure

	#-------------------------------------
	return user._connection.open_editor('acl', info, ok, ko)
